/**
 * Copyright (c) 2012-2013 Nokia Corporation. All rights reserved.
 * Nokia and Nokia Connecting People are registered trademarks of Nokia Corporation.
 * Oracle and Java are trademarks or registered trademarks of Oracle and/or its
 * affiliates. Other product and company names mentioned herein may be trademarks
 * or trade names of their respective owners.
 * See LICENSE.TXT for license information.
 */

package com.nokia.example.amaze.model;

/**
 * A general, easy-to-use timer. 
 */
public class MyTimer {
    // Constants
    private static final int MAX_LISTENER_COUNT = 5;
    
    // Members
    private static MyTimer _instance = null;
    private MyListener[] _listeners = null;
    private long _time = 0;
    
    /** 
     * @return The singleton instance of MyTimer.
     */
    static public MyTimer instance() {
        if (_instance == null) {
            _instance = new MyTimer();
        }
        
        return _instance;
    }
    
    /**
     * Constructor.
     */
    private MyTimer() {
        _listeners = new MyListener[MAX_LISTENER_COUNT];
    }

    /**
     * Updates the internal time of the timer. If enough time has passed, the
     * timer will trigger (call the listener(s)).
     * @param time The current time.
     */
    public void update(final long time) {
        _time = time;
        MyListener listener = null;
        
        for (int i = 0; i < MAX_LISTENER_COUNT; ++i) {
            listener = _listeners[i];
            
            if (listener == null) {
                continue;
            }
            
            if (_time - listener._lastTime >= listener._interval) {
                // Notify the listener
                listener._object.onTimeout();
                
                if (listener._repeat) {
                    listener._lastTime = _time;
                }
                else {
                    // Not repetitive. Thus, remove the listener
                    _listeners[i] = null;
                }
            }
        }
    }
    
    /**
     * For convenience.
     */
    public void update() {
        update(System.currentTimeMillis());
    }        
    
    /**
     * Adds the given listener.
     * @param listener The listener to add.
     * @param repeat If true, the timer will call the listener repeatedly.
     * @param interval The interval (or delay) for calling the listener.
     * @return True if the listener was added successfully, false otherwise.
     */
    public boolean addListener(Listener listener,
                               boolean repeat,
                               int interval)
    {
        if (listener == null || interval <= 0) {
            return false;
        }
        
        for (int i = 0; i < MAX_LISTENER_COUNT; ++i) {
            if (_listeners[i] != null
                    && _listeners[i]._object == listener)
            {
                // Listener already exists
                System.out.println("MyTimer::addListener(): Listener already exists.");
                return false;
            }
        }
        
        for (int i = 0; i < MAX_LISTENER_COUNT; ++i) {
            if (_listeners[i] == null) {
                MyListener myListener = new MyListener();
                myListener._object = listener;
                myListener._repeat = repeat;
                myListener._interval = interval;
                myListener._lastTime = System.currentTimeMillis();
                _listeners[i] = myListener;
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * Removes the given listener.
     * @param listener The listener to remove.
     * @return True if the listener was found and removed, false otherwise.
     */
    public boolean removeListener(Listener listener) {
        if (listener != null) {
            for (int i = 0; i < MAX_LISTENER_COUNT; ++i) {
                if (_listeners[i] != null && _listeners[i]._object == listener) {
                    _listeners[i] = null;
                    return true;
                }
            }
        }
        
        return false;
    }
    
    /**
     * Interface for the listeners.
     */
    public interface Listener {
        void onTimeout();
    }
    
    /**
     * Internal class for reserving the meta information related to a listener.
     */
    private class MyListener {
        private Listener _object;
        private boolean _repeat = false;
        private int _interval = 0; // Milliseconds
        private long _lastTime = 0;
    }
}
